package com.xteam.xnetworkdisk.scheduled;

import com.baomidou.mybatisplus.core.conditions.query.LambdaQueryWrapper;
import com.xteam.xnetworkdisk.constant.Constant;
import com.xteam.xnetworkdisk.constant.FIleTypeConstant;
import com.xteam.xnetworkdisk.sys.dao.FileDao;
import com.xteam.xnetworkdisk.sys.entity.FileEntity;
import com.xteam.xnetworkdisk.utils.ChunkFileLocalUtils;
import com.xteam.xnetworkdisk.utils.FileLocalUtils;
import com.xteam.xnetworkdisk.utils.MinioUtilsOld;
import com.xteam.xnetworkdisk.utils.RedisUtils;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.data.redis.core.SetOperations;
import org.springframework.scheduling.annotation.Scheduled;
import org.springframework.stereotype.Component;

import java.io.File;
import java.util.List;
import java.util.Set;
import java.util.concurrent.TimeUnit;
import java.util.stream.Collectors;

@Component
public class DeleteFileScheduler {

    @Autowired
    private FileDao fileDao;
//    @Autowired
//    private MinioUtilsOld minioUtils;
    @Autowired
    private FileLocalUtils fileLocalUtils;

    @Autowired
    private ChunkFileLocalUtils chunkFileLocalUtils;


    private static final String DIRECTORY_PATH = System.getProperty("user.home") + File.separator + "xnetworkdisk";
    private static final String TEMP_PATH = DIRECTORY_PATH + File.separator + "temp";
    @Autowired
    private RedisUtils redisUtils;

    // 定时任务，定期执行删除操作
    @Scheduled(cron = "0 0 3 * * ?") // 每天凌晨三点执行
    public void deleteFile() {
        // 获取文件信息
        LambdaQueryWrapper<FileEntity> wrapper = new LambdaQueryWrapper<>();
        wrapper.eq(FileEntity::getFileId,Constant.TEMP_FOLDER);
        List<FileEntity> fileEntities = fileDao.selectList(wrapper);
        if (fileEntities == null || fileEntities.isEmpty()) {
            return;
        }
        for (FileEntity fileEntity : fileEntities) {
            deleteFileRecursive(fileEntity);
        }
    };

    private void deleteFileRecursive(FileEntity fileEntity) {
        // 判断是否为文件夹
        Boolean isFolder = fileEntity.getIsFolder();

        if (isFolder) {

            // 获取文件夹中的所有文件和子文件夹
            LambdaQueryWrapper<FileEntity> wrapper = new LambdaQueryWrapper<>();
            wrapper.eq(FileEntity::getFolderId,fileEntity.getFileId());
            List<FileEntity> children = fileDao.selectList(wrapper);

            // 递归删除子文件和子文件夹
            for (FileEntity child : children) {
                deleteFileRecursive(child);
            }
        }

        String filePath = fileEntity.getFilePath();

        // 删除当前文件或文件夹
        if(fileEntity.getFileType() != null && fileEntity.getFileType() == FIleTypeConstant.VIDEO){

            String videoThumbnail = filePath + "_thumbnail.png";
            fileLocalUtils.deleteFile(videoThumbnail);
        }
        fileLocalUtils.deleteFile(filePath);
        fileDao.deleteById(fileEntity);
    }


    /**
     * 每天凌晨3点执行，清理Redis中过期的分片文件
     */
    @Scheduled(cron = "0 0 3 * * ?")  // 每天凌晨3点执行
    public void cleanupExpiredChunks() {
        Set<String> keys = redisUtils.keys("file:upload:chunks:*");

        if (keys == null || keys.isEmpty()) {
            return;
        }
        for (String key : keys) {
            String md5Value = key.substring("file:upload:chunks:".length());

            Boolean lock = redisUtils.lock(md5Value);
            if(!lock){
                continue;
            }

            try {
                SetOperations<String, Object> setOps = redisUtils.getSetOperations();
                Set<Object> uploadedChunks = setOps.members(key);
                Set<Integer> uploadedChunkNumbers = uploadedChunks.stream()
                        .map(Object::toString) // 将 Object 转换为 String
                        .map(Integer::valueOf) // 将 String 转换为 Integer
                        .collect(Collectors.toSet());

                // 删除temp目录中的分片文件
                chunkFileLocalUtils.clearFileUploadCacheArray(md5Value,uploadedChunkNumbers);
                // 删除Redis中的键
                redisUtils.delete(key);
            } finally {
                // 无论如何都要解锁
                redisUtils.unlock(md5Value);
            }
        }
    }


}
